import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        ArrayList<User> list=new ArrayList<>();//存放账户的集合
        int a;//用于存储操作数
        Scanner sc=new Scanner(System.in);//创建对象,从屏幕获取操作数
        int index=-1;//用于存储用户在集合中的索引
        boolean mark=false;//用于判断是否销户成功
        while (true) {
            do {
               loginMenu();//用户菜单

               do{
                   a=sc.nextInt();//获取操作数
                   switch (a){//判断操作数
                       case 1 ->index=login(list);//若为1,进行登录,并把用户在集合中的索引赋值给index
                       case 2 ->registe(list);//若为2,进行注册
                       default -> System.out.println("请正确输入操作数");//若为其他则提醒用户重新输入
                   }
               }while (a!=1&&a!=2);//若操作数正确,则跳出循环
           }while (a!=1||index<0);//若为登录操作,且用户账号存在则跳出循环
            do {
                mainmenu();//主菜单
                a=sc.nextInt();//获取操作数
                switch (a){//判断用户操作数
                    case 1->inquire(list,index);//查询用户详细信息
                    case 2->deposit(list,index);//取款功能
                    case 3->withdraw(list,index);//存款功能
                    case 4->transfer(list,index);//转账功能
                    case 5->modify(list,index);//修改密码功能
                    case 6->a=6;
                    case 7-> {//销户功能,并将销户是否成功的结果传给mark
                        mark=cancelAccount(list, index);
                    }
                    default -> System.out.println("操作数有误");//操作数有误提醒
                }
                if(a==5||a==6||mark)break;//若修改密码成功,退出账号,销户成功,都跳出循环
            } while (true);
        }
    }

    /**
     * 销户功能
     * @param list 账户集合
     * @param index 用户账户在集合中的索引
     * @return 销户是否成功
     */
    private static boolean cancelAccount(ArrayList<User> list, int index) {
        Scanner sc=new Scanner(System.in);//创建扫描对象
        System.out.println("是否确定销户(y/n)");
        String ok=sc.next();//获取用户操作符
        if(ok.equals("y"))//判断是否销户
           if(list.get(index).getBalance()==0) {//判断用户账户是否存在余额
               list.remove(index);//从账户集合中消除当前用户账户
               System.out.println("销户成功,请登录其他账号");
               return true;//销户成功,放回true
           }
        else {
               System.out.println("销户失败,账户中存在余额,余额:"+list.get(index).getBalance());
               return false;//存在余额,注销失败返回false
           }
        else {
            System.out.println("你的账号已经保留");
            return false;//取消注销账户,放回false
        }
    }

    /**
     * 修改账户密码
     * @param list 账号集合
     * @param index 用户账号在集合中对应的索引
     */
    private static void modify(ArrayList<User> list, int index) {
        Scanner sc=new Scanner(System.in);//创建扫描对象
        boolean sign=false;//判断是否成功修改密码
        System.out.println("***欢迎来到ATM管理系统******");
        System.out.println("请输入当前账户密码:");
        while (true) {
            if(sc.next().equals(list.get(index).getPassword())){//获取输入密码,判断于原密码是否相同
                System.out.println("密码正确");
                while (true) {
                    System.out.println("请输入新的密码->");
                    String str=new String(sc.next());//获取新的密码
                    System.out.println("请输入确认密码->");
                    for (int i=0;i<3;i++) {//三次确认密码机会
                        if(sc.next().equals(str)){//判断密码是否一致
                            System.out.println("密码一致,修改成功");
                            System.out.println("请重新输入");
                            list.get(index).setPassword(str);//修改用户账号中的原密码
                            sign=true;//修改成功的标志
                            break;//修改成功.跳出循环
                        }
                        else {//密码不一致提醒
                            System.out.println("密码不一致,还剩"+(2-i)+"次机会");
                            System.out.println("请重新输入确认密码->");
                        }
                    }
                    if(sign)break;//修改成功,跳出循环
                    else continue;//修改失败,重新进入循环
                }
                break;
            }
            else {
                System.out.println("密码有误,请重新输入->");//密码有误提醒
            }
        }
    }

    /**
     * 转账功能
     * @param list 账户集合
     * @param index 用户账户在集合中对应的索引
     */
    private static void transfer(ArrayList<User> list, int index) {
        Scanner sc=new Scanner(System.in);//创建扫描对象
        boolean sign=false;//判断卡号是否存在
        int length=listsize(list);//获取账户集合中实际用户数
        if(length<2){//判断用户是否超过2个
            System.out.println("无可转账账户");
            return;//结束方法
        }
        if(list.get(index).getBalance()<=0) {//判断用户是否有余额
            System.out.println("余额不足");
            System.out.println("当前余额:"+list.get(index).getBalance());//用户余额提醒
            return;//结束方法
        }

        while (true) {
            System.out.println("请输入转帐对象卡号");
            int opindex=idContain(list,sc.next());//获取转账对象卡号,并查询集合中对应账户的索引
            if(opindex<0)//判断用户是否存在
                System.out.println("卡号不存在,请重新输入卡号->");
            else {
                if(opindex==index)//判断用户是否为自己
                System.out.println("对不起,你不能给自己转账");
                else {
                for(int i=0;i<3;i++) {//3次验证机会
                    if (verify(list, opindex)) {//验证转账用户是否认识
                        sign=true;//转账成功的标志
                        System.out.println("************");
                        System.out.println("请输入转账金额");
                        Double number = sc.nextDouble();//获取转账金额
                        while (!ifmoney(list, index, number)) {//判断金额是否合理
                            number = sc.nextDouble();//重新获取转账金额
                        }
                        list.get(index).reduce(number);//扣除当前用户账户余额
                        list.get(opindex).increase(number);//增加对象用户余额
                        System.out.println("转账成功" + number + "元");
                        System.out.println("账户还剩"+list.get(index).getBalance()+"元");
                        break;//转账成功,结束循环
                    }
                    else System.out.println("还剩"+(2-i)+"次验证机会");//验证机会提醒
                }
               if(sign)break;//转账成功结束循环
               else continue;//转账失败继续循环
            }
            }
        }
    }

    /**
     * 验证转账对象是否认识
     * @param list 账户集合
     * @param opindex 转账对象账户在集合中对应的索引
     * @return 验证是否通过的标志
     */
    private static boolean verify(ArrayList<User> list, int opindex) {
        Scanner sc=new Scanner(System.in);//创建扫描对象
        System.out.println("你当前为*"+list.get(opindex).getName().substring(1)+"转账");//转账提醒
        System.out.println("请输入姓氏确定->");
       String firstname=new String(list.get(opindex).getName().substring(0,1));//截取转账对象的姓
        if(sc.next().equals(firstname))//判断用户输入的姓是否与转账对象相同
            return true;
        else return false;
    }

    /**
     * 计算集合实际用户数
     * @param list 账户集合
     * @return 实际用户数
     */
    private static int listsize(ArrayList<User> list) {
        int count=0;//用于记录用户数
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i)!=null)//判断用户是否注销
                count++;
        }
        return count;
    }

    /**
     * 判断金额是否合理
     * @param list 账户集合
     * @param index 用户账户在集合中对应的索引
     * @param number 金额
     * @return
     */
    private static boolean ifmoney(ArrayList<User> list, int index,double number){
        if(number>list.get(index).getLimite()) {//判断是否超过限额
            System.out.println("超出当次取款最高额度"+list.get(index).getLimite()+",请重新输入取款金额");
            System.out.println("你当前余额"+list.get(index).getBalance());
            return false;
        }
        else if(number>list.get(index).getBalance()) {//判断余额是否足够
            System.out.println("超出余额,请重新输入取款金额");
            System.out.println("你当前余额"+list.get(index).getBalance());
            return false;
        }
        else return true;
    }

    /**
     * 收款功能
     * @param list 账户集合
     * @param index 用户账户在集合中对应的索引
     */
    private static void withdraw(ArrayList<User> list, int index) {
        if(list.get(index).getBalance()<100)//判断用户余额是否足够
        {
            System.out.println("对不起,余额不足100,无法取款");
            System.out.println("你当前余额"+list.get(index).getBalance());
            return;//余额不足,结束循环
        }
        System.out.println("****欢迎来到ATM管理系统*****");
        System.out.println("请输入取款金额");
        Scanner sc=new Scanner(System.in);//创建扫描对象
        double number;//获取取款金额
        number= sc.nextDouble();//获取取款金额
        while (!ifmoney(list,index,number)){//判断金额是否合理
            number=sc.nextDouble();//重新获取取款金额
        }
        list.get(index).reduce(number);//在用户账户扣除金额
        System.out.println("取款成功"+number+"元");
        inquire(list,index);//显示用户详细信息
    }

    /**
     * 存款功能
     * @param list 账户集合
     * @param index 用户账户在集合中对应的索引
     */
    private static void deposit(ArrayList<User> list, int index) {
        System.out.println("****欢迎来到ATM管理系统*****");
        System.out.println("请输入存款金额");
        Scanner sc=new Scanner(System.in);//新建扫描对象
        double number=sc.nextDouble();//获取存款金额
        list.get(index).increase(number);//在用户中增加金额
        System.out.println("存款成功");
        inquire(list,index);//显示用户账户详细信息
    }

    /**
     * 显示用户详细信息
     * @param list 账户集合
     * @param index 用户账户在集合中对应的索引
     */
    private static void inquire(ArrayList<User> list,int index) {
        System.out.println("****用户详情界面*******");
        System.out.println("你的账户信息如下");
        System.out.println("卡号"+list.get(index).getId());
        System.out.println("姓名"+list.get(index).getName());
        System.out.println("余额"+list.get(index).getBalance());
        System.out.println("当次取现最高额度"+list.get(index).getLimite());
    }

    /**
     * 主菜单
     */
    public static void mainmenu(){
        System.out.println("*****欢迎来到ATM系统********");
        System.out.println("1-查询");
        System.out.println("2-存款");
        System.out.println("3-取款");
        System.out.println("4-转帐");
        System.out.println("5-修改密码");
        System.out.println("6-退出");
        System.out.println("7-注销账户");
    }

    /**
     * 用户登录菜单
     */
    public static void loginMenu(){//用户登录菜单
        System.out.println("***欢迎来的ATM管理系统***");
        System.out.println("1-登录账户");
        System.out.println("2-注册账户");
        System.out.println("请输入1或2选择对应操作");
        System.out.println("请选择你的操作->");
    }

    /**
     * //判断集合中是否存在卡号并返回对应的索引
     * @param list 账户集合
     * @param id    用户账户在集合中对应的索引
     * @return
     */
    public static int idContain(ArrayList<User> list,String id){
        for (int i = 0; i < list.size(); i++) {//遍历集合
            if(list.get(i).getId().equals(id))//判断卡号是否一致
                return i;//若一致返回索引
        }
        return -1;//若不存在返回-1
    }

    /**
     * 判断集合是否存在用户名,并返回对应索引
     * @param list 账户集合
     * @param name 用户账户在集合中对应的索引
     * @return
     */
    public static int nameContain(ArrayList<User> list,String name){
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).getName().equals(name))//判断账户集合中用户名是否与输入相同
            return i;//放回对应索引
        }
        return -1;//若不存在,则返回-1
    }

    /**
     * 生成随机卡号
     * @return 返回随机卡号
     */
    public static String randomId(){
        Random r=new Random();//新建随机数对象
        StringBuilder sb=new StringBuilder();//新建字符串处理对象
        for (int i = 0; i < 8; i++) {//生成8位0-9随机数
            sb.append(r.nextInt(10));//连接8随机数成字符串
        }
        return sb.toString();//放回连接的字符串
    }

    /**
     * 登录功能
     * @param list 账户集合
     * @return 返回用户账户在集合中对应的索引
     */
    public static int login(ArrayList<User> list){
        if(list.size()==0){//判断集合中是否存在账户
            System.out.println("不存在账户,请重新开户");
            return -1;//若不存在返回-1
        }
        Scanner sc=new Scanner(System.in);//创建扫描对象
        System.out.println("请输入卡号");
        int index=idContain(list,sc.next());//获取用户卡号,并将账户在集合中的索引赋值给index
       while (index<0){//判断账户是否存在
           System.out.println("请重新输入卡号");
           index=idContain(list,sc.next());//重新获取用户卡号,并将账户在集合中的索引赋值给index
       }
        System.out.println("请输入密码");
        while (!list.get(index).getPassword().equals(sc.next())){//获取密码,并判断输入密码于账号密码是否一致
            System.out.println("密码错误");//错误提醒
            System.out.println("请重新输入密码");
        }
        System.out.println(list.get(index).getName()+"欢迎加入ATM系统,你的卡号为"+list.get(index).getId());//欢迎用户
        return index;//返回用户账户在集合中的索引
    }

    /**
     * 注册功能
     * @param list 账户集合
     */
    public static void registe(ArrayList<User> list){//开户功能
        User u=new User();//创建新的用户对象
        Scanner sc=new Scanner(System.in);//创建扫描对象,从屏幕获取操作数
        System.out.println("****开户操作*****");//登录界面
        System.out.println("请输入账户名称");
        u.setName(sc.next());//获取用户名
        while(nameContain(list,u.getName())>=0){//判断集合中用户名是否存在
            System.out.println("账号名存在");//存在提醒界面
            System.out.println("请重新输入账户名->");
            u.setName(sc.next());//获取新的用户名
        }
            System.out.println("请输入初始密码");
            u.setPassword(sc.next());//获取登录密码
            System.out.println("请再次输入确认密码");
         while (!u.getPassword().equals(sc.next())){//获取确认密码,并判断是否一致
             System.out.println("两次密码不一致,请重新设置密码");//密码不一致提醒
             System.out.println("请输入初始密码");
             u.setPassword(sc.next());//重新获取密码
             System.out.println("请再次输入确认密码");
         }
        do{
            u.setId(randomId());//获取随机不重复卡号
        }while (idContain(list,u.getId())>0);//判断卡号是否存在
        System.out.println("请输入当次限额");
        u.setLimite(sc.nextDouble());//获取当次最高限额
        while(u.getLimite()<=0){//判断最高限额是否大于0
            System.out.println("请正确输入限额");
            u.setLimite(sc.nextDouble());//重新获取最高限额
        }
        list.add(u);//将新建的用户加入集合
        System.out.println("注册成功");
        System.out.println("你的卡号为:"+u.getId()+"请记住");//显示开户卡号
    }
}
